/*
 * %W% %E%
 *
 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.sun.corba.se.impl.transport;

import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.omg.CORBA.INITIALIZE;
import org.omg.CORBA.INTERNAL;
import org.omg.CORBA.CompletionStatus;

import com.sun.corba.se.pept.transport.Acceptor;
import com.sun.corba.se.pept.transport.ConnectionCache;
import com.sun.corba.se.pept.transport.ByteBufferPool;
import com.sun.corba.se.pept.transport.ContactInfo;
import com.sun.corba.se.pept.transport.InboundConnectionCache;
import com.sun.corba.se.pept.transport.OutboundConnectionCache;
import com.sun.corba.se.pept.transport.Selector;

import com.sun.corba.se.spi.ior.IORTemplate;
import com.sun.corba.se.spi.ior.ObjectAdapterId;
import com.sun.corba.se.spi.orb.ORB;
import com.sun.corba.se.spi.transport.CorbaAcceptor;
import com.sun.corba.se.spi.transport.CorbaTransportManager;

// REVISIT - impl/poa specific:
import com.sun.corba.se.impl.oa.poa.Policies;
import com.sun.corba.se.impl.orbutil.ORBUtility;

/**
 * @author Harold Carr
 */
public class CorbaTransportManagerImpl 
    implements
	CorbaTransportManager
{
    protected ORB orb;
    protected List acceptors;
    protected Map outboundConnectionCaches;
    protected Map inboundConnectionCaches;
    protected Selector selector;
    
    public CorbaTransportManagerImpl(ORB orb) 
    {
	this.orb = orb;
	acceptors = new ArrayList();
	outboundConnectionCaches = new HashMap();
	inboundConnectionCaches = new HashMap();
	selector = new SelectorImpl(orb);
    }

    ////////////////////////////////////////////////////
    //
    // pept TransportManager
    //

    public ByteBufferPool getByteBufferPool(int id)
    {
	throw new RuntimeException(); 
    }

    public OutboundConnectionCache getOutboundConnectionCache(
        ContactInfo contactInfo) 
    {
	synchronized (contactInfo) {
	    if (contactInfo.getConnectionCache() == null) {
		OutboundConnectionCache connectionCache = null;
		synchronized (outboundConnectionCaches) {
		    connectionCache = (OutboundConnectionCache)
			outboundConnectionCaches.get(
                            contactInfo.getConnectionCacheType());
		    if (connectionCache == null) {
			// REVISIT: Would like to be able to configure
			// the connection cache type used.
			connectionCache = 
			    new CorbaOutboundConnectionCacheImpl(orb,
								 contactInfo);
			outboundConnectionCaches.put(
                            contactInfo.getConnectionCacheType(),
			    connectionCache);
		    }
		}
		contactInfo.setConnectionCache(connectionCache);
	    }
	    return contactInfo.getConnectionCache();
	}
    }

    public Collection getOutboundConnectionCaches()
    {
	return outboundConnectionCaches.values();
    }

    public InboundConnectionCache getInboundConnectionCache(
        Acceptor acceptor) 
    {
	synchronized (acceptor) {
	    if (acceptor.getConnectionCache() == null) {
		InboundConnectionCache connectionCache = null;
		synchronized (inboundConnectionCaches) {
		    connectionCache = (InboundConnectionCache)
			inboundConnectionCaches.get(
                            acceptor.getConnectionCacheType());
		    if (connectionCache == null) {
			// REVISIT: Would like to be able to configure
			// the connection cache type used.
			connectionCache = 
			    new CorbaInboundConnectionCacheImpl(orb,
								acceptor);
			inboundConnectionCaches.put(
                            acceptor.getConnectionCacheType(),
			    connectionCache);
		    }
		}
		acceptor.setConnectionCache(connectionCache);
	    }
	    return acceptor.getConnectionCache();
	}
    }

    public Collection getInboundConnectionCaches()
    {
	return inboundConnectionCaches.values();
    }

    public Selector getSelector(int id) 
    {
	return selector;
    }

    public synchronized void registerAcceptor(Acceptor acceptor) 
    {
	if (orb.transportDebugFlag) {
	    dprint(".registerAcceptor->: " + acceptor);
	}
	acceptors.add(acceptor);
	if (orb.transportDebugFlag) {
	    dprint(".registerAcceptor<-: " + acceptor);
	}
    }

    public Collection getAcceptors()
    {
	return getAcceptors(null, null);
    }

    public synchronized void unregisterAcceptor(Acceptor acceptor)
    {
	acceptors.remove(acceptor);
    }

    public void close()
    {
	try {
	    if (orb.transportDebugFlag) {
		dprint(".close->");
	    }
            for (Object cc : outboundConnectionCaches.values()) {
              ((ConnectionCache)cc).close() ;
            }
            for (Object cc : inboundConnectionCaches.values()) {
              ((ConnectionCache)cc).close() ;
            }
	    getSelector(0).close();
	} finally {
	    if (orb.transportDebugFlag) {
		dprint(".close<-");
	    }
	}
    }

    ////////////////////////////////////////////////////
    //
    // CorbaTransportManager
    //

    public Collection getAcceptors(String objectAdapterManagerId,
				   ObjectAdapterId objectAdapterId)
    {
	// REVISIT - need to filter based on arguments.

	// REVISIT - initialization will be moved to OA.
	// Lazy initialization of acceptors.
	Iterator iterator = acceptors.iterator();
	while (iterator.hasNext()) {
	    Acceptor acceptor = (Acceptor) iterator.next();
	    if (acceptor.initialize()) {
		if (acceptor.shouldRegisterAcceptEvent()) {
		    orb.getTransportManager().getSelector(0)
			.registerForEvent(acceptor.getEventHandler());
		}
	    }
	}
	return acceptors;
    }

    // REVISIT - POA specific policies
    public void addToIORTemplate(IORTemplate iorTemplate, 
				 Policies policies,
				 String codebase,
				 String objectAdapterManagerId,
				 ObjectAdapterId objectAdapterId)
    {
	Iterator iterator = 
	    getAcceptors(objectAdapterManagerId, objectAdapterId).iterator();
	while (iterator.hasNext()) {
	    CorbaAcceptor acceptor = (CorbaAcceptor) iterator.next();
	    acceptor.addToIORTemplate(iorTemplate, policies, codebase);
	}
    }


    ////////////////////////////////////////////////////
    //
    // implemenation
    //

    protected void dprint(String msg)
    {
	ORBUtility.dprint("CorbaTransportManagerImpl", msg);
    }
}

// End of file.
